home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / read_bmp.pro < prev    next >
Text File  |  1997-07-08  |  7KB  |  223 lines

  1. ; $Id: read_bmp.pro,v 1.9 1997/03/12 20:46:43 stevep Exp $
  2. ;
  3. ; Copyright (c) 1993-1997, Research Systems, Inc.  All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5.  
  6. FUNCTION READ_BMP, File, Red, Green, Blue, Ihdr, RGB=rgb
  7. ; Copyright (c) 1993, Research Systems, Inc.  All rights reserved.
  8. ;    Unauthorized reproduction prohibited.
  9. ;+
  10. ; NAME:
  11. ;    READ_BMP
  12. ;
  13. ; PURPOSE:
  14. ;     This function reads a Microsoft Windows Version 3 device
  15. ;    independent bitmap file (.BMP).
  16. ;
  17. ; CATEGORY:
  18. ;       Input/Output
  19. ;
  20. ; CALLING SEQUENCE:
  21. ;       Result = READ_BMP(File [, R, G, B [, IHDR]])
  22. ;
  23. ; INPUTS:
  24. ;     File: The full path name of the bitmap file to read.
  25. ;
  26. ; OUTPUTS:
  27. ;    This function returns a byte array containing the image
  28. ;    from the bitmap file. In the case of 4-bit or 8-bit images,
  29. ;    the dimensions of the resulting array are [biWidth, biHeight];
  30. ;    for 16 and 24-bit decomposed color images the dimensions are
  31. ;    [3, biWidth, biHeight].
  32. ;    Dimensions are taken from the BITMAPINFOHEADER of the file.
  33. ;    NOTE: for 24 bit images, unless the RGB keyword is supplied,
  34. ;    color interleaving is blue, green, red;
  35. ;    i.e. result[0,i,j] = blue, result[1,i,j] = green, etc.
  36. ;
  37. ; OPTIONAL OUTPUTS:
  38. ;       R, G, B:  Color tables from the file. There 16 elements each for
  39. ;          4 bit images, 256 elements each for 8 bit images. Not
  40. ;          defined or used for 16 and 24 bit images.
  41. ;      Ihdr:      A structure containing BITMAPINFOHEADER from file.
  42. ;          Tag names are as defined in the MS Windows Programmer's
  43. ;          Reference Manual, Chapter 7.
  44. ;
  45. ; KEYWORDDS:
  46. ;    RGB:    If this keyword is supplied, and a 16 or 24-bit image is read,
  47. ;        color interleaving of the result is R, G, B, rather than BGR.
  48. ;        Result[0,i,j] = red, Result[1,i,j] = green, and
  49. ;        Result[2,i,j] = blue.
  50. ; SIDE EFFECTS:
  51. ;       IO is performed.
  52. ;
  53. ; RESTRICTIONS:
  54. ;       DOES NOT HANDLE: 1 bit deep images, or compressed images.
  55. ;       Is not fast for 4 bit images. Works best on images where the
  56. ;       number of bytes in each scan-line is evenly divisible by 4.
  57. ;
  58. ; PROCEDURE:
  59. ;       Straightforward. Will work on both big endian and little endian
  60. ;    machines.
  61. ;
  62. ; EXAMPLE:
  63. ;       TV, READ_BMP('c:\windows\party.bmp', r, g, b)     ;Read & display image
  64. ;       TVLCT, r, g, b                          ;Load it's colors
  65. ;
  66. ; MODIFICATION HISTORY:
  67. ;   DMS, RSI.   March 1993.       Original version.
  68. ;   DMS, RSI.   May, 1993.    Now works on all machines...
  69. ;   DMS, RSI.   Nov, 1996    Added support for 16-bit RGB and RGB keyword.
  70. ;-
  71.  
  72. on_ioerror, bad
  73. on_error, 2         ;Return on error
  74.  
  75. openr, unit, file, /GET_LUN, /BLOCK
  76. fhdr = { BITMAPFILEHEADER, $
  77.     bftype: bytarr(2), $        ;A two char string
  78.     bfsize: 0L, $
  79.     bfreserved1: 0, $
  80.     bfreserved2: 0, $
  81.     bfoffbits: 0L $
  82.   }
  83. readu, unit, fhdr           ;Read the bitmapfileheader
  84. if string(fhdr.bftype) ne "BM" then begin
  85.     free_lun,unit
  86.     message, 'File '+file+' is not in bitmap file format'
  87. endif
  88.  
  89. ihdr = { BITMAPINFOHEADER, $
  90.     bisize: 0L, $
  91.     biwidth: 0L, $
  92.     biheight: 0L, $
  93.     biplanes: 0, $
  94.     bibitcount: 0, $
  95.     bicompression: 0L, $
  96.     bisizeimage: 0L, $
  97.     bixpelspermeter: 0L, $
  98.     biypelspermeter: 0L, $
  99.     biclrused: 0L, $
  100.     biclrimportant: 0L $
  101.   }
  102.  
  103.  
  104. readu, unit, ihdr
  105.  
  106. big_endian = (byte(1,0,2))[0] eq 0b
  107. if big_endian then begin        ;Big endian machine?
  108.     fhdr = swap_endian(fhdr)        ;Yes, swap it
  109.     ihdr = swap_endian(ihdr)
  110.     endif
  111.  
  112. if ihdr.bibitcount eq 1 then begin
  113.      free_lun, unit
  114.      message, 'Can''t handle monochrome images'
  115. endif
  116. if ihdr.bicompression ne 0 then begin
  117.     free_lun, unit
  118.     message, 'Can''t handle compressed images'
  119. endif
  120.  
  121.     ;Pseudo color?
  122. if (ihdr.bibitcount ne 24) and (ihdr.bibitcount ne 16)  then begin
  123.     colors = bytarr(4, 2^ihdr.bibitcount)
  124.     readu, unit, colors             ;Read colors
  125.     red = reform(colors[2, *])        ;Decommutate colors
  126.     green = reform(colors[1, *])
  127.     blue = reform(colors[0, *])
  128.     endif
  129.  
  130. nx = ihdr.biwidth        ;Columns
  131. ny = ihdr.biheight        ;Rows
  132.  
  133. point_lun, unit, fhdr.bfoffbits     ;Point to data...
  134.  
  135. case ihdr.bibitcount of            ;How many bits/pixel?
  136. 4: begin
  137.     a = bytarr(nx, ny, /nozero)
  138.     buff = bytarr(nx/2, /nozero)   ;Line buffer
  139.     even = lindgen(nx/2) * 2
  140.     odd = even + 1
  141.     if nx and 1 then pad = 0B       ;interbyte padding
  142.     i = (n_elements(buff) + n_elements(pad)) and 3  ;bytes we have
  143.     if i ne 0 then pad = bytarr(4-i+n_elements(pad))
  144.     for i=0, ny-1 do begin
  145.         if n_elements(pad) ne 0 then readu, unit, buff, pad $
  146.         else readu, unit, buff
  147.         a[even, i] = ishft(buff, -4)
  148.         a[odd, i] = buff and 15b
  149.         if nx and 1 then a[nx-1, i] = ishft(pad[0], -4) ;Last odd byte?
  150.         endfor
  151.     endcase
  152.  
  153. 8:  begin
  154.     a = bytarr(nx, ny, /nozero)
  155.     if (nx and 3) eq 0 then readu, unit, a $          ;Slam dunk it
  156.     else begin                      ;Must read line by line...
  157.        pad = bytarr(4 - (nx and 3))
  158.        buff = bytarr(nx, /nozero)
  159.        for i=0, ny-1 do begin       ;Each line
  160.            readu, unit, buff, pad
  161.            a[0,i] = buff
  162.            endfor
  163.        endelse
  164.     endcase            ;8 bits/pixel
  165.  
  166. 16: begin            ;16 bits/pixel
  167. ;        bits(0:4) = blue
  168. ;        bits(5:9) = green
  169. ;        bits(10:14) = red
  170.     a = intarr(nx * ny, /nozero)    ;Read as a 1D array
  171.     if  (nx and 1) eq 0 then readu, unit, a $  ;If even # of cols, no padding
  172.     else begin
  173.         pad = 0            ;Pad 1 16 bit word
  174.         buff = intarr(nx, /nozero)
  175.         for i=0, ny-1 do begin
  176.             readu, unit, buff, pad
  177.             a[i * nx] = buff        ;Insert line
  178.             endfor
  179.     endelse
  180.     if big_endian then byteorder, a, /sswap
  181.     r = byte(ishft(a,-7) and 248)    ;Shift down 10 and up 3
  182.     g = byte(ishft(a,-2) and 248)    ;down 5 and up 3
  183.     a = byte(ishft(a, 3) and 248)    ;up 3, really blue
  184.     if keyword_set(RGB) then a = [r,g,a] $  ;Unswitch it?
  185.     else a = [a,g,r]
  186.  
  187.     a = reform(a, nx * ny, 3, /overwrite)    ;Diddle to 3,nx,ny
  188.     a = transpose(temporary(a))        ;Color interleave in 1st dimension
  189.     a = reform(a,3,nx,ny,/overwrite)
  190.     endcase            ;16 bits
  191.  
  192. 24: begin                    ;24 bits / pixel....
  193.     a = bytarr(3, nx, ny, /nozero)
  194.     if ((3 * nx) and 3) eq 0 then readu, unit, a $  ;Again, dunk it.
  195.     else begin
  196.         pad = bytarr(4 - ((3 * nx) and 3))
  197.         buff = bytarr(3, nx, /nozero)
  198.         for i=0, ny-1 do begin
  199.             readu, unit, buff, pad
  200.             a[0,0, i] = buff            ;Insert line
  201.             endfor
  202.     endelse
  203.     if keyword_set(RGB) then begin    ;Unswitch it?
  204.     buff = a[0,*,*]
  205.     a[0,0,0] = a[2,*,*]
  206.     a[2,0,0] = buff
  207.     endif
  208.     endcase            ;24bits
  209. else: begin
  210.        free_lun,unit
  211.        Message,'Can not handle '+strtrim(ihdr.bibitcount,2)+' bits/pixel'
  212.       endcase
  213. endcase
  214.  
  215. free_lun, unit
  216. return, a
  217.  
  218. bad:  if n_elements(unit) gt 0 then free_lun, unit
  219. Message, 'Can''t open (or read)' + file
  220. return, 0
  221. end
  222.  
  223.